home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Fatted Calf
/
The Fatted Calf.iso
/
Applications
/
Communication
/
Conference
/
Source
/
Controller.m
< prev
next >
Wrap
Text File
|
1993-01-19
|
20KB
|
852 lines
/* Generated by Interface Builder */
#import "Controller.h"
#import <stdio.h>
#import <syscall.h>
#import <pwd.h>
#import <strings.h>
#import <sys/types.h>
#import <netdb.h>
#import <signal.h>
#import <defaults.h>
#import <objc/Storage.h>
#import <soundkit/Sound.h>
@implementation Controller
void killCr(char *c, int len)
{
int i;
for(i=0;((i<len) && (c[i]!='\0'));i++)
if (c[i] == '\n')
c[i] = '\0';
return;
}
int membercmp(MemberRecord *r1, MemberRecord *r2)
{
return ((!strncmp(r1->user,r2->user,STRING_LENGTH)) &&
(!strncmp(r1->username,r2->username,STRING_LENGTH)) &&
(!strncmp(r1->machine,r2->machine,STRING_LENGTH)));
}
void copymember(MemberRecord *r1, MemberRecord *r2)
{
strncpy(r1->user,r2->user,STRING_LENGTH);
strncpy(r1->username,r2->username,STRING_LENGTH);
strncpy(r1->machine,r2->machine,STRING_LENGTH);
r1->port = r2->port;
return;
}
DPSTimedEntryProc networkEntryHandler(DPSTimedEntry num,
double now,
char *userData)
{
[(id)userData doNetworkTimedEntry:(id)userData];
return 0;
}
DPSTimedEntryProc alarmEntryHandler(DPSTimedEntry num,
double now,
char *userData)
{
[(id)userData doAlarmTimedEntry:(id)userData];
return 0;
}
- init
{
[super init];
alertSound = nil;
numberAlarms = 0;
netTimedEntry = 0;
return self;
}
- addMachineQuit:sender
{
[NXApp abortModal];
return self;
}
- addMachineOk:sender
{
[NXApp stopModal];
return self;
}
- fetchSound:sender
{
id pan;
const char * const tps[2] = {"snd",NULL};
char str[STRING_LENGTH];
pan = [OpenPanel new];
[pan allowMultipleFiles:NO];
if ([pan runModalForTypes:tps]) {
if (alertSound)
[alertSound free];
strncpy(str,[pan filename],STRING_LENGTH);
if (str && str[0])
alertSound = [[Sound alloc] initFromSoundfile:str];
else
alertSound = nil;
[soundFileTextField setStringValue:str];
[self setDefaults:soundFileTextField];
}
return self;
}
- doAlarmTimedEntry:sender
{
if (numberAlarms < (MAXALARMS *2)) {
numberAlarms++;
[coverButton setState:(![coverButton state])];
} else {
numberAlarms = 0;
DPSRemoveTimedEntry(alarmTimedEntry);
[coverButton setState:NO];
}
return self;
}
- handleAlarm
{
if ([noisyAlertSwitch state]) {
if (alertSound)
[alertSound play:self];
else
NXBeep();
}
if ([visualAlertSwitch state]) {
alarmTimedEntry=DPSAddTimedEntry(ALARMENTRYPERIOD,
(DPSTimedEntryProc)alarmEntryHandler,
(void *)self,
30);
}
if ([activateOnAlertSwitch state]) {
if ([NXApp isHidden])
[NXApp unhide:self];
}
return self;
}
- doOutput:(char *)msg withSender:(MemberRecord *)owner andBold:(BOOL)bold
{
int l;
id p;
char str[STRING_LENGTH*3+10];
[self getBrowserString:str fromMember:owner];
sprintf(str,"%s: ",str);
p = [logText docView];
l = [p textLength];
[p setSel:l :l];
[p replaceSel:str];
[p setSel:l :[p textLength]];
if (bold)
[p setSelFontStyle:NX_BOLD];
else
[p setSelFontStyle:NX_ITALIC];
l = [p textLength];
[p setSel:l :l];
[p replaceSel:msg];
l = [p textLength];
[p setSel:l :l];
[p replaceSel:"\n"];
l = [p textLength];
[p setSel:l :l];
return self;
}
- input:sender
{
id matrix;
int i,s;
MemberRecord *temp;
char str[1024];
i = [sender textLength];
if (1024 < i)
i = 1024;
[sender selectAll:self];
s = [sender getSubstring:str start:0 length:i];
[sender replaceSel:""];
str[s] = '\0';
[self doOutput:str withSender:(&me) andBold:YES];
matrix = [memberBrowser matrixInColumn:0];
for(i=0;(i<[matrix cellCount]);i++) {
if ([[matrix cellAt:i :0] state]) {
temp = [memberStore elementAt:i];
[speak setSendPort:temp->port];
[speak sendMessage:str from:(char *)(&me) length:(sizeof(me))];
}
}
[sender selectText:self];
return self;
}
- quit:sender
{
int i;
MemberRecord *temp;
for(i=0;(i<[memberStore count]);i++) {
temp = [memberStore elementAt:i];
[speak setSendPort:temp->port];
[speak goodByeIAmLeaving:(char *)(&me) length:(sizeof(me))];
}
[memberStore free];
[listen removePort];
[listen free];
[speak free];
[NXApp terminate:self];
return self;
}
- (BOOL)gotMemberWithMachine:(const char *)machine
{
int i;
MemberRecord *temp;
for(i=0;(i<[memberStore count]);i++) {
temp = [memberStore elementAt:i];
if (!strncmp(temp->machine,machine,STRING_LENGTH))
return YES;
}
return NO;
}
- (BOOL)gotMember:(MemberRecord *)mem
{
int i;
MemberRecord *temp;
for(i=0;(i<[memberStore count]);i++) {
temp = [memberStore elementAt:i];
if (membercmp(mem,temp))
return YES;
}
return NO;
}
- changePref:sender
{
[self setDefaults:sender];
return self;
}
- getDefaults:sender
{
const char *c;
c = NXReadDefault([NXApp appName],"ShowLogin");
[loginSwitch setState:((c == NULL) || (!strncmp("YES",c,3)))];
c = NXReadDefault([NXApp appName],"ShowReal");
[realSwitch setState:((c != NULL) && (!strncmp("YES",c,3)))];
c = NXReadDefault([NXApp appName],"ShowMachine");
[machineSwitch setState:((c != NULL) && (!strncmp("YES",c,3)))];
c = NXReadDefault([NXApp appName],"UseConference");
[useConferenceSwitch setState:((c == NULL) || (!strncmp("YES",c,3)))];
c = NXReadDefault([NXApp appName],"UseNetwork");
[useNetworkSwitch setState:((c != NULL) && (!strncmp("YES",c,3)))];
c = NXReadDefault([NXApp appName],"UseNoiseAlert");
[noisyAlertSwitch setState:((c != NULL) && (!strncmp("YES",c,3)))];
c = NXReadDefault([NXApp appName],"UseVisualAlert");
[visualAlertSwitch setState:((c == NULL) || (!strncmp("YES",c,3)))];
c = NXReadDefault([NXApp appName],"ActivateOnAlert");
[activateOnAlertSwitch setState:((c != NULL) && (!strncmp("YES",c,3)))];
c = NXReadDefault([NXApp appName],"SoundFile");
[soundFileTextField setStringValue:c];
return self;
}
- setDefaults:sender
{
char str[10];
char param[20];
const char *c;
char strn[64];
// Yes, in case you were wondering, this _is_ Evil, not to mention
// sloppy in the extreme.
if (sender == loginSwitch)
strncpy(param,"ShowLogin",20);
else if (sender == realSwitch)
strncpy(param,"ShowReal",20);
else if (sender == machineSwitch)
strncpy(param,"ShowMachine",20);
else if (sender == useConferenceSwitch)
strncpy(param,"UseConference",20);
else if (sender == useNetworkSwitch)
strncpy(param,"UseNetwork",20);
else if (sender == noisyAlertSwitch)
strncpy(param,"UseNoiseAlert",20);
else if (sender == visualAlertSwitch)
strncpy(param,"UseVisualAlert",20);
else if (sender == activateOnAlertSwitch)
strncpy(param,"ActivateOnAlert",20);
else if (sender == soundFileTextField) {
NXWriteDefault([NXApp appName],"SoundFile",[sender stringValue]);
if (alertSound)
[alertSound free];
c = [sender stringValue];
if (c && c[0]) {
strncpy(strn,c,64);
alertSound = [[Sound alloc] initFromSoundfile:str];
}
return self;
}
if ([sender state])
strncpy(str,"YES",10);
else
strncpy(str,"NO",10);
NXWriteDefault([NXApp appName],param,str);
if ((sender == useConferenceSwitch) && ([sender state]) &&
(NX_ALERTDEFAULT==NXRunAlertPanel("Hey!","Load .Conference File now?",
"Ok","Cancel",NULL)))
[self doConferenceFile:self];
if ((sender == useNetworkSwitch) && ([sender state]) &&
(NX_ALERTDEFAULT==NXRunAlertPanel("Hey!","Scan network now?",
"Ok","Cancel",NULL)))
[self doNetwork:self];
[memberBrowser reloadColumn:0];
return self;
}
- selectAllMembers:sender
{
id p;
int i;
p = [memberBrowser matrixInColumn:0];
for(i=0;(i<[p cellCount]);i++) {
[p selectCellAt:i :0];
}
return self;
}
- connectTo:(const char *)machine
{
int s;
MemberRecord *temp;
int i;
port_t pt;
if ((!machine) || (!machine[0]) || (machine[0] == '\0'))
return self;
for(i=0;(i<[memberStore count]);i++) {
temp = [memberStore elementAt:i];
if (!strncmp(machine,temp->machine,STRING_LENGTH))
return self;
}
s=NXRunAlertPanel("Hey!",
"Attempt to connect to %s?",
"Connect","Do Not Connect",NULL,machine);
if (s == NX_ALERTDEFAULT) {
pt = NXPortNameLookup(APPNAME,machine);
if (PORT_NULL!=pt) {
[speak setSendPort:pt];
[speak helloIAm:(char *)(&me) length:(sizeof(me))];
}
}
return self;
}
- disconnectFrom:(const char *)machine
{
int s;
MemberRecord *temp;
int i;
for(i=0;(i<[memberStore count]);i++) {
temp = [memberStore elementAt:i];
if (!strncmp(machine,temp->machine,STRING_LENGTH)) {
s = NXRunAlertPanel("Hey!",
"Attempt to disconnect from %s?",
"Disconnect","Stay Connected",NULL,machine);
if (s == NX_ALERTDEFAULT) {
[speak setSendPort:temp->port];
[speak goodByeIAmLeaving:(char *)&me length:sizeof(me)];
[memberStore removeAt:i];
return self;
}
}
}
return self;
}
- connectMember:sender
{
char c[STRING_LENGTH];
[addMachinePanel makeKeyAndOrderFront:self];
[addMachineField selectText:self];
if (NX_RUNABORTED == [NXApp runModalFor:addMachinePanel]) {
[addMachinePanel close];
return self;
}
[addMachinePanel close];
strncpy(c,[addMachineField stringValue],STRING_LENGTH);
killCr(c,STRING_LENGTH);
[self connectTo:c];
[memberBrowser reloadColumn:0];
return self;
}
- disconnectMember:sender
{
id p;
int i;
char c[STRING_LENGTH];
MemberRecord *temp;
c[0] = '\0';
p = [memberBrowser matrixInColumn:0];
for(i=0;(i<[memberStore count]);i++) {
temp = [memberStore elementAt:i];
if ([[p cellAt:i :0] state]) {
strncpy(c,temp->machine,STRING_LENGTH);
killCr(c,STRING_LENGTH);
}
}
if (c[0]) {
[self disconnectFrom:c];
}
[memberBrowser reloadColumn:0];
return self;
}
- connectMachine:sender
{
id p,q;
char c[STRING_LENGTH];
p = machineBrowser;
q = [[p matrixInColumn:[p selectedColumn]] selectedCell];
if (q == nil)
return self;
strncpy(c,[q stringValue],STRING_LENGTH);
killCr(c,STRING_LENGTH);
[self connectTo:c];
[memberBrowser reloadColumn:0];
return self;
}
- disconnectMachine:sender
{
id p,q;
char c[STRING_LENGTH];
p = machineBrowser;
q = [[p matrixInColumn:[p selectedColumn]] selectedCell];
if (q == nil)
return self;
strncpy(c,[q stringValue],STRING_LENGTH);
killCr(c,STRING_LENGTH);
[self disconnectFrom:c];
[memberBrowser reloadColumn:0];
return self;
}
- addMachineToConferenceFile:(const char *)machine
{
FILE *fd;
char str[STRING_LENGTH+30];
char lstr[STRING_LENGTH];
char *cont;
sprintf(str,"%s/%s",homedir,".ConferenceMachines");
fd = fopen(str,"r");
if (fd != NULL) {
for(cont = fgets(lstr,STRING_LENGTH,fd);
cont;
cont = fgets(lstr,STRING_LENGTH,fd)) {
killCr(lstr,STRING_LENGTH);
if (!strncmp(lstr,machine,STRING_LENGTH)) {
fclose(fd);
return self;
}
}
fclose(fd);
}
fd = fopen(str,"a");
if (fd != NULL) {
fputs(machine,fd);
fputc('\n',fd);
fclose(fd);
} else {
fd = fopen(str,"w");
if (fd != NULL) {
fputs(machine,fd);
fputc('\n',fd);
fclose(fd);
}
}
return self;
}
- removeMachineFromConferenceFile:(const char *)machine
{
FILE *fd;
char str[STRING_LENGTH+30];
char lstr[STRING_LENGTH];
int i;
char *cont;
char mach[STRING_LENGTH];
id tempStore;
strncpy(mach,machine,STRING_LENGTH);
killCr(mach,STRING_LENGTH);
tempStore = [[Storage alloc] initCount:0
elementSize:(sizeof(char) * STRING_LENGTH)
description:MACHINESTORAGEDESCRIPTION];
sprintf(str,"%s/%s",homedir,".ConferenceMachines");
fd = fopen(str,"r");
if (fd != NULL) {
for(cont = fgets(lstr,STRING_LENGTH,fd);
cont;
cont = fgets(lstr,STRING_LENGTH,fd)) {
killCr(lstr,STRING_LENGTH);
if (strncmp(lstr,mach,STRING_LENGTH)) {
[tempStore addElement:lstr];
}
}
fclose(fd);
}
fd = fopen(str,"w");
if (fd == NULL)
return self;
for(i=0;(i<[tempStore count]);i++) {
fputs([tempStore elementAt:i],fd);
fputc('\n',fd);
}
fclose(fd);
[tempStore free];
return self;
}
- addMachine:sender
{
char c[STRING_LENGTH];
[addMachinePanel makeKeyAndOrderFront:self];
[addMachineField selectText:self];
if (NX_RUNABORTED == [NXApp runModalFor:addMachinePanel]) {
[addMachinePanel close];
return self;
}
[addMachinePanel close];
strncpy(c,[addMachineField stringValue],STRING_LENGTH);
killCr(c,STRING_LENGTH);
if (c[0]) {
[self addMachineToConferenceFile:c];
[machineBrowser reloadColumn:0];
if (strncmp(me.machine,c,STRING_LENGTH)) {
[self connectTo:c];
[memberBrowser reloadColumn:0];
}
}
return self;
}
- removeMachine:sender
{
id p,q;
char c[STRING_LENGTH];
p = machineBrowser;
q = [[p matrixInColumn:[p selectedColumn]] selectedCell];
if (q == nil)
return self;
strncpy(c,[q stringValue],STRING_LENGTH);
killCr(c,STRING_LENGTH);
if (c && c[0]) {
[self removeMachineFromConferenceFile:c];
[machineBrowser reloadColumn:0];
if (strncmp(me.machine,c,STRING_LENGTH))
[self disconnectFrom:c];
[memberBrowser reloadColumn:0];
}
return self;
}
- getBrowserString:(char *)str fromMember:(MemberRecord *)mem
{
str[0] = '\0';
if ([loginSwitch state]) {
sprintf(str,"%s",mem->user);
}
if ([realSwitch state]) {
if (str[0])
sprintf(str,"%s (%s)",str,mem->username);
else
sprintf(str,"(%s)",mem->username);
}
if ([machineSwitch state]) {
if (str[0])
sprintf(str,"%s@%s",str,mem->machine);
else
sprintf(str,"%s",mem->machine);
}
return self;
}
- yeahRight:sender
{
if (!strcmp([sender title],"Thomas K. Burkholder")) {
[sender setTitle:"Waddya want, a picture?"];
} else {
[sender setTitle:"Thomas K. Burkholder"];
}
return self;
}
- doConferenceFile:sender
{
char *cont;
port_t pt;
FILE *fd;
char str[STRING_LENGTH+30];
sprintf(str,"%s/%s",homedir,".ConferenceMachines");
fd = fopen(str,"r");
if (fd == NULL)
return self;
for(cont = fgets(str,STRING_LENGTH,fd);
cont;
cont = fgets(str,STRING_LENGTH,fd)) {
killCr(str,STRING_LENGTH);
if ((![self gotMemberWithMachine:str]) &&
(strncmp("localhost",str,STRING_LENGTH)) &&
(strncmp("broadcasthost",str,STRING_LENGTH)) &&
(strncmp(me.machine,str,STRING_LENGTH))) {
pt = NXPortNameLookup(APPNAME,str);
if (PORT_NULL!=pt) {
[speak setSendPort:pt];
[speak helloIAm:(char *)(&me) length:(sizeof(me))];
}
}
}
return self;
}
- doNetworkTimedEntry:sender
{
port_t pt;
struct hostent *he;
he = gethostent();
if (he == NULL) {
DPSRemoveTimedEntry(netTimedEntry);
netTimedEntry = 0;
return self;
}
if ((![self gotMemberWithMachine:he->h_name]) &&
(strncmp("localhost",he->h_name,STRING_LENGTH)) &&
(strncmp("broadcasthost",he->h_name,STRING_LENGTH)) &&
(strncmp(me.machine,he->h_name,STRING_LENGTH))) {
pt = NXPortNameLookup(APPNAME,he->h_name);
if (PORT_NULL!=pt) {
[speak setSendPort:pt];
[speak helloIAm:(char *)(&me) length:(sizeof(me))];
}
}
return self;
}
- doNetwork:sender
{
sethostent(1);
if (!netTimedEntry)
netTimedEntry = DPSAddTimedEntry(NETWORKENTRYPERIOD,
(DPSTimedEntryProc)networkEntryHandler,
(void *)self,
NX_BASETHRESHOLD);
return self;
}
- appDidInit:sender
{
struct passwd *pwent;
char str[64];
const char *c;
[self getDefaults:sender];
// Initialize sound alert
c = [soundFileTextField stringValue];
if (c && c[0]) {
strncpy(str,c,64);
alertSound = [[Sound alloc] initFromSoundfile:str];
}
// Initialize visual alert
alertWindow = [NXApp appIcon];
[[alertWindow setContentView:coverButton] free];
pwent = getpwuid(getuid());
strncpy(homedir,pwent->pw_dir,STRING_LENGTH);
strncpy(me.user,pwent->pw_name,STRING_LENGTH);
sscanf(pwent->pw_gecos,"%[^,]",me.username);
gethostname(me.machine,STRING_LENGTH);
killCr(me.machine,STRING_LENGTH);
memberStore = [[Storage alloc] initCount:0
elementSize:(sizeof(MemberRecord))
description:MEMBERSTORAGEDESCRIPTION];
speak = [[ConferenceSpeaker alloc] init];
listen = [[ConferenceListener alloc] init];
[listen setDelegate:self];
[listen checkInAs:APPNAME];
[listen addPort];
if ([useConferenceSwitch state])
[self doConferenceFile:self];
[machineBrowser reloadColumn:0];
if ([useNetworkSwitch state])
[self doNetwork:self];
[memberBrowser reloadColumn:0];
[[inputText docView] setDelegate:self];
[[inputText docView] setCharFilter:(NXCharFilterFunc)NXFieldFilter];
[[inputText window] makeKeyAndOrderFront:self];
[[inputText docView] selectAll:sender];
return self;
}
-(int)browser:sender fillMatrix:matrix inColumn:(int)column
{
id currentCell;
int i;
if (sender == memberBrowser) {
MemberRecord *temp;
char l[STRING_LENGTH*3 + 10];
for(i=0;(i<[memberStore count]);i++) {
[matrix addRow];
currentCell = [matrix cellAt:i :column];
temp = [memberStore elementAt:i];
[self getBrowserString:l fromMember:temp];
[currentCell setStringValue:l];
[currentCell setLeaf:YES];
[currentCell setLoaded:YES];
[currentCell setTag:i];
}
return i;
} else { // sender is machineBrowser
FILE *fd;
char str[STRING_LENGTH+30];
char lstr[STRING_LENGTH];
char *cont;
sprintf(str,"%s/%s",homedir,".ConferenceMachines");
fd = fopen(str,"r");
if (fd == NULL)
return 0;
for(i = 0,cont = fgets(lstr,STRING_LENGTH,fd);
cont;
cont = fgets(lstr,STRING_LENGTH,fd)) {
if (lstr && lstr[0] && (lstr[0] != '\n')) {
[matrix addRow];
currentCell = [matrix cellAt:i:0];
[currentCell setStringValue:lstr];
[currentCell setLeaf:YES];
[currentCell setLoaded:YES];
[currentCell setTag:i];
i++;
}
}
fclose(fd);
return i;
}
}
- textDidEnd:sender endChar:(unsigned short)whyEnd
{
if (whyEnd != 0)
[self input:sender];
return self;
}
- (int)helloIAm:(char *)fr length:(int)len
{
MemberRecord temp,*mr;
mr = (MemberRecord *)fr;
if ([self gotMember:mr])
return 0;
copymember(&temp,mr);
temp.port = NXPortNameLookup(APPNAME,mr->machine);
[memberStore addElement:&temp];
[speak setSendPort:temp.port];
[speak helloIAm:(char *)(&me) length:(sizeof(me))];
[memberBrowser reloadColumn:0];
return 0;
}
- (int)goodByeIAmLeaving:(char *)fr length:(int)len
{
int i;
MemberRecord *temp;
for(i=0;(i<[memberStore count]);i++) {
temp = [memberStore elementAt:i];
if (membercmp((MemberRecord *)fr,temp)) {
[memberStore removeAt:i];
}
}
[memberBrowser reloadColumn:0];
return 0;
}
- (int)sendMessage:(char *)msg from:(char *)fr length:(int)len
{
id p;
if ([NXApp isHidden]) {
[self handleAlarm];
}
[self doOutput:msg withSender:(MemberRecord *)fr andBold:NO];
p = [inputText docView];
[p setSel:[p textLength] :[p textLength]];
return 0;
}
@end